package com.bestcem.xm.common.core.uitls;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * Email 工具类
 *
 * @author yf.wang <yf.wang@idiaoyan.com>
 * @version V1.0
 * @date 2021/10/14
 */
@Slf4j
public class EmailUtil {

    private final static String ATEXT = "a-zA-Z0-9_\\-";

    private final static String DOT_ATOM_TEXT = "[" + ATEXT + "]+(?:\\.[" + ATEXT + "]+)*";

    // private final static String ATEXT_UTF8 = ATEXT + "\\u0080-" + "\\udbff\\udfff";
    private final static String ATEXT_UTF8 = ATEXT + "\\u4e00-\\u9fa5";

    private final static String DOT_ATOM_TEXT_UTF8 = "[" + ATEXT_UTF8 + "]+(?:\\.[" + ATEXT_UTF8 + "]+)*";

    private final static String ATEXT_HOSTNAME = "(?:(?:[a-zA-Z0-9][a-zA-Z0-9\\-]*)?[a-zA-Z0-9])";
    private final static String DOMAIN_PATTERN = ATEXT_HOSTNAME + "(?:\\." + ATEXT_HOSTNAME + ")*";


    private final static Integer EMAIL_MAX_LENGTH = 254;
    private final static Integer LOCAL_PART_MAX_LENGTH = 64;
    private final static Integer DOMAIN_MAX_LENGTH = 255;

    private final static String EMAIL_SIGN = "@";
    private final static String SPOT = ".";


    /**
     * 校验邮箱格式
     *
     * @param email
     * @return
     */
    public static Boolean validateEmail(String email) {

        if (StrUtil.isBlank(email)) {
            log.error("【邮箱】校验失败 {} 为空", email);
            return false;
        }

        if (!email.contains(EMAIL_SIGN)) {
            log.error("【邮箱】校验失败 {} 不包含@", email);
            return false;
        }

        String[] split = email.split(EMAIL_SIGN);
        if (split.length != 2) {
            log.error("【邮箱】校验失败 {} 包含多个@", email);
            return false;
        }

        // 校验用户名
        if (!validateLocalPart(split[0])) {
            return false;
        }
        // 校验域名
        if (!validateDomainPart(split[1])) {
            return false;
        }
        return true;
    }

    /**
     * 校验域名
     *
     * @param domain
     * @return
     */
    private static boolean validateDomainPart(String domain) {
        if (StrUtil.isBlank(domain)) {
            log.error("【邮箱】域名 校验失败 {} 为空", domain);
            return false;
        }

        if (!domain.contains(SPOT)) {
            log.error("【邮箱】域名 校验失败 {} 不包含.", domain);
            return false;
        }

        if (domain.startsWith(SPOT)) {
            log.error("【邮箱】域名 校验失败 {} 以.开头", domain);
            return false;
        }

        if (domain.endsWith(SPOT)) {
            log.error("【邮箱】域名 校验失败 {} 以.结尾", domain);
            return false;
        }

        if (domain.length() > DOMAIN_MAX_LENGTH) {
            log.error("【邮箱】域名 校验失败 {} 过长, 超过 {} ", domain, DOMAIN_MAX_LENGTH);
            return false;
        }

        if (!domain.matches(DOMAIN_PATTERN)) {
            log.error("【邮箱】域名 校验失败 域名 匹配失败 {} ", domain, DOMAIN_PATTERN);
            return false;
        }
        return true;
    }

    /**
     * 校验用户名
     *
     * @param local
     * @return
     */
    private static boolean validateLocalPart(String local) {
        if (StrUtil.isBlank(local)) {
            log.error("【邮箱】用户名 校验失败  {} 为空", local);
            return false;
        }

        if (local.length() > LOCAL_PART_MAX_LENGTH) {
            log.error("【邮箱】用户名 校验失败 {} 过长, 超出", local, LOCAL_PART_MAX_LENGTH);
            return false;
        }

        if (!local.matches(DOT_ATOM_TEXT)) {
            if (!local.matches(DOT_ATOM_TEXT_UTF8)) {
                log.error("【邮箱】用户名 校验失败  {} 匹配失败 {}", local, DOT_ATOM_TEXT_UTF8);
                return false;
            }
        }
        return true;
    }
}
